home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / sendmail / sendmail-5.65c+IDA-1.4.4.1 / src / clock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-20  |  5.4 KB  |  255 lines

  1. /*
  2.  * Copyright (c) 1983 Eric P. Allman
  3.  * Copyright (c) 1988 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms are permitted provided
  7.  * that: (1) source distributions retain this entire copyright notice and
  8.  * comment, and (2) distributions including binaries display the following
  9.  * acknowledgement:  ``This product includes software developed by the
  10.  * University of California, Berkeley and its contributors'' in the
  11.  * documentation or other materials provided with the distribution and in
  12.  * all advertising materials mentioning features or use of this software.
  13.  * Neither the name of the University nor the names of its contributors may
  14.  * be used to endorse or promote products derived from this software without
  15.  * specific prior written permission.
  16.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  17.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  18.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19.  */
  20.  
  21. #ifndef lint
  22. static char sccsid[] = "@(#)clock.c    5.8 (Berkeley) 6/1/90";
  23. static char rcsid[] = "@(#)$Id: clock.c,v 5.8.0.13 1991/06/21 12:36:40 paul Exp $";
  24. #endif /* not lint */
  25.  
  26. #include "sendmail.h"
  27. #include <sys/signal.h>
  28.  
  29. static SIG_TYPE tick();
  30. static void endsleep();
  31.  
  32. /*
  33. **  SETEVENT -- set an event to happen at a specific time.
  34. **
  35. **    Events are stored in a sorted list for fast processing.
  36. **    An event only applies to the process that set it.
  37. **
  38. **    Parameters:
  39. **        intvl -- intvl until next event occurs.
  40. **        func -- function to call on event.
  41. **        arg -- argument to func on event.
  42. **
  43. **    Returns:
  44. **        none.
  45. **
  46. **    Side Effects:
  47. **        none.
  48. */
  49.  
  50. EVENT *
  51. setevent(intvl, func, arg)
  52.     TIME_TYPE intvl;
  53.     void (*func)();
  54.     int arg;
  55. {
  56.     register EVENT **evp;
  57.     register EVENT *ev;
  58.     auto TIME_TYPE now;
  59.  
  60.     if (intvl <= 0)
  61.     {
  62.         syserr("setevent: intvl=%ld\n", intvl);
  63.         return (NULL);
  64.     }
  65.  
  66.     (void) time(&now);
  67.  
  68.     /* search event queue for correct position */
  69.     for (evp = &EventQueue; (ev = *evp) != NULL; evp = &ev->ev_link)
  70.     {
  71.         if (ev->ev_time >= (TIME_TYPE)now + intvl)
  72.             break;
  73.     }
  74.  
  75.     /* insert new event */
  76.     ev = (EVENT *) xalloc(sizeof *ev);
  77.     ev->ev_time = (TIME_TYPE)now + intvl;
  78.     ev->ev_func = func;
  79.     ev->ev_arg = arg;
  80.     ev->ev_pid = getpid();
  81.     ev->ev_link = *evp;
  82.     *evp = ev;
  83.  
  84.     if (tTd(5, 5))
  85.         printf("setevent: intvl=%ld, for=%ld, func=%x, arg=%d, ev=%x\n",
  86.             intvl, (TIME_TYPE)now + intvl, func, arg, ev);
  87.  
  88.     (void) tick();
  89.     return (ev);
  90. }
  91. /*
  92. **  CLREVENT -- remove an event from the event queue.
  93. **
  94. **    Parameters:
  95. **        ev -- pointer to event to remove.
  96. **
  97. **    Returns:
  98. **        none.
  99. **
  100. **    Side Effects:
  101. **        arranges for event ev to not happen.
  102. */
  103.  
  104. void
  105. clrevent(ev)
  106.     register EVENT *ev;
  107. {
  108.     register EVENT **evp;
  109.  
  110.     if (tTd(5, 5))
  111.         printf("clrevent: ev=%x\n", ev);
  112.     if (ev == NULL)
  113.         return;
  114.  
  115.     /* find the parent event */
  116.     (void) signal(SIGALRM, SIG_IGN);
  117.     for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link)
  118.     {
  119.         if (*evp == ev)
  120.             break;
  121.     }
  122.  
  123.     /* now remove it */
  124.     if (*evp != NULL)
  125.     {
  126.         *evp = ev->ev_link;
  127.         free((char *) ev);
  128.     }
  129.  
  130.     /* restore clocks and pick up anything spare */
  131.     (void) tick();
  132. }
  133. /*
  134. **  TICK -- take a clock tick
  135. **
  136. **    Called by the alarm clock.  This routine runs events as needed.
  137. **
  138. **    Parameters:
  139. **        none.
  140. **
  141. **    Returns:
  142. **        none.
  143. **
  144. **    Side Effects:
  145. **        calls the next function in EventQueue.
  146. */
  147.  
  148. static SIG_TYPE
  149. tick()
  150. {
  151.     register TIME_TYPE now;
  152.     register EVENT *ev;
  153.     int mypid = getpid();
  154.  
  155.     (void) signal(SIGALRM, SIG_IGN);
  156.     (void) alarm(0);
  157.     now = curtime();
  158.  
  159.     if (tTd(5, 4))
  160.         printf("tick: now=%ld\n", now);
  161.  
  162.     while ((ev = EventQueue) != NULL &&
  163.            (ev->ev_time <= now || ev->ev_pid != mypid))
  164.     {
  165.         void (*f)();
  166.         int arg;
  167.         int pid;
  168.  
  169.         /* process the event on the top of the queue */
  170.         ev = EventQueue;
  171.         EventQueue = EventQueue->ev_link;
  172.         if (tTd(5, 6))
  173.             printf("tick: ev=%x, func=%x, arg=%d, pid=%d\n", ev,
  174.                 ev->ev_func, ev->ev_arg, ev->ev_pid);
  175.  
  176.         /* we must be careful in here because ev_func may not return */
  177.         (void) signal(SIGALRM, tick);
  178. #ifdef SIGVTALRM
  179.         /* reset 4.2bsd signal mask to allow future alarms */
  180. # ifdef LACK_SIGBLOCK
  181.         {
  182.             sigset_t set = SIGALRM;
  183.             (void) sigprocmask(SIG_UNBLOCK, &set, NULL);
  184.         }
  185. # else /* !LACK_SIGBLOCK */
  186. #  ifndef sigmask
  187. #   define sigmask(m)    (1<<((m)-1))
  188. #  endif /* !sigmask */
  189.         (void) sigsetmask(sigblock(0) & ~sigmask(SIGALRM));
  190. # endif /* LACK_SIGBLOCK */
  191. #endif /* SIGVTALRM */
  192.  
  193.         f = ev->ev_func;
  194.         arg = ev->ev_arg;
  195.         pid = ev->ev_pid;
  196.         free((char *) ev);
  197.         if (pid != getpid())
  198.             continue;
  199.         if (EventQueue != NULL)
  200.         {
  201.             if (EventQueue->ev_time > now)
  202.                 (void) alarm((unsigned) (EventQueue->ev_time - now));
  203.             else
  204.                 (void) alarm(3);
  205.         }
  206.         (*f)(arg);
  207.         (void) alarm(0);
  208.         now = curtime();
  209.     }
  210.     (void) signal(SIGALRM, tick);
  211.     if (EventQueue != NULL)
  212.         (void) alarm((unsigned) (EventQueue->ev_time - now));
  213. #ifdef notdef
  214. #if ( SIG_TYPE == int )
  215.     return(0);
  216. #endif /* SIG_TYPE == int */
  217. #endif /* notdef */
  218. }
  219. /*
  220. **  XSLEEP -- a version of sleep that works with this stuff
  221. **
  222. **    Because sleep uses the alarm facility, I must reimplement
  223. **    it here.
  224. **
  225. **    Parameters:
  226. **        intvl -- time to sleep.
  227. **
  228. **    Returns:
  229. **        none.
  230. **
  231. **    Side Effects:
  232. **        waits for intvl time.  However, other events can
  233. **        be run during that interval.
  234. */
  235.  
  236. static bool    SleepDone;
  237.  
  238. void
  239. Xsleep(intvl)
  240.     unsigned int intvl;
  241. {
  242.     if (intvl == 0)
  243.         return;
  244.     SleepDone = FALSE;
  245.     (void) setevent((TIME_TYPE) intvl, endsleep, 0);
  246.     while (!SleepDone)
  247.         pause();
  248. }
  249.  
  250. static void
  251. endsleep()
  252. {
  253.     SleepDone = TRUE;
  254. }
  255.